import sys
from PySide6.QtWidgets import (QApplication, QWidget, QTableWidget, 
                             QTableWidgetItem, QVBoxLayout, QLabel,
                             QTextEdit, QSplitter)
from PySide6.QtCore import Qt, QMimeData, QDataStream
import PySide6.QtGui as QtGui
import PySide6.QtCore as QtCore

from PySide6.QtGui import QDrag, QColor,QStandardItemModel
class DataParserTable(QTableWidget):
    """用于演示解析application/x-qabstractitemmodeldatalist格式的表格"""
    def __init__(self, parent=None):
        super().__init__(4, 3, parent)
        self.setHorizontalHeaderLabels(["列1", "列2", "列3"])
        self.setSelectionMode(QTableWidget.ExtendedSelection)
        self.setDragDropMode(QTableWidget.DragDrop)
        self.setDefaultDropAction(Qt.CopyAction)
        
        # 填充示例数据（包含不同角色的信息）
        self._init_data()
        
        # 用于显示解析结果的文本编辑框
        self.parser_output = QTextEdit()
        self.parser_output.setReadOnly(True)
        self.parser_output.setPlaceholderText("拖放数据后将显示解析结果...")
        self.row_=-1
        self.col_=-1

    def _init_data(self):
        """初始化表格数据，包含多种数据角色"""
        for row in range(4):
            for col in range(3):
                item = QTableWidgetItem(f"单元格 ({row+1},{col+1})")
                item.setTextAlignment(Qt.AlignCenter)
                
                # 设置额外的数据角色
                item.setToolTip(f"提示: 这是第{row+1}行第{col+1}列")  # ToolTipRole
                if (row + col) % 2 == 0:
                    item.setBackground(QColor(240, 248, 255))  # BackgroundRole
                    item.setForeground(QColor(0, 0, 139))      # ForegroundRole
                
                self.setItem(row, col, item)
        self.prohibited_cells = {
                    (0, 0),  # 行索引从0开始
                    (3, 1)   # 第4行第2列
                }
    def dropEvent(self, event):
        if event.mimeData().hasFormat('application/x-qabstractitemmodeldatalist'):
            data = event.mimeData()
            source_item = QtGui.QStandardItemModel()
            source_item.dropMimeData(data, QtCore.Qt.CopyAction, 0,0, QtCore.QModelIndex())
            print(source_item.item(0, 0).text()) 
            data = event.mimeData().data("application/x-qabstractitemmodeldatalist")
        
            stream = QDataStream(data, QDataStream.ReadOnly)
            row = stream.readInt32()
            col = stream.readInt32()
            d=stream.readInt32()
            print(row,col,d)
            roles = {}
            for _ in range(d):
                # 读取角色（32位整数）
                role = stream.readInt32()
                # 读取值（QVariant类型）
                value = stream.readQVariant()

                roles[role] = value
            print(roles)
    # 重写：拖入时检查目标单元格是否允许接收
    def dragMoveEvent(self, event):
        # 先验证数据来源和格式
        # if not (event.mimeData().hasText() and event.source() is not None and event.source() != self):
        #     event.ignore()
        #     return
        
        # 获取当前鼠标位置对应的单元格
        pos = event.pos()
        index = self.indexAt(pos)
        event.answerRect()
        event.accept()
        if index.isValid():
            row, col = index.row(), index.column()
            if(self.row_!=row or self.col_!=col):
                self.row_=row
                self.col_=col
                item=self.item(row,col)
                print(row,col,"DME")
            # 检查是否为禁止拖入的单元格
            if (row, col) in self.prohibited_cells:
                event.ignore()  # 禁止拖入
                md=event.mimeData()
                items_=self.items(md.data)
                for i in items_:
                    print(i)
                return
        
        # 允许拖入
        event.acceptProposedAction()    
    def DragEnterEvent(self, event):
        # 先验证数据来源和格式
        # if not (event.mimeData().hasText() and event.source() is not None and event.source() != self):
        #     event.ignore()
        #     return
        
        # 获取当前鼠标位置对应的单元格
        pos = event.pos()
        index = self.indexAt(pos)
        print("DragEnterEvent")
        if index.isValid():
            row, col = index.row(), index.column()
            # 检查是否为禁止拖入的单元格
            if (row, col) in self.prohibited_cells:
                event.ignore()  # 禁止拖入
                return
        
        # 允许拖入
        event.acceptProposedAction()
    def _parse_model_data(self, mime_data):
        """解析application/x-qabstractitemmodeldatalist格式数据"""
        # 获取二进制数据
        data = mime_data.data("application/x-qabstractitemmodeldatalist")
        
        # 使用QDataStream读取二进制数据
        stream = QDataStream(data, QDataStream.ReadOnly)
        
        # 存储解析结果的列表
        parsed_items = []
        
        # 读取项目数量（32位整数）
        item_count = stream.readInt32()
        
        for _ in range(item_count):
            # 读取行索引和列索引（都是32位整数）
            row = stream.readInt32()
            col = stream.readInt32()
            # 读取角色-值对的数量
            role_count = stream.readInt32()
            
            # 存储当前项目的所有角色-值对
            roles = {}
            for _ in range(role_count):
                # 读取角色（32位整数）
                role = stream.readInt32()
                # 读取值（QVariant类型）
                value = stream.readQVariant()
                roles[role] = value
            
            # 将解析结果添加到列表
            parsed_items.append({
                "row": row,
                "col": col,
                "roles": roles
            })
            
        return parsed_items

    def _show_parsed_data(self, parsed_data):
        """在文本框中显示解析后的数据"""
        self.parser_output.clear()
        self.parser_output.append("解析 application/x-qabstractitemmodeldatalist 结果：\n")
        self.parser_output.append(f"总共有 {len(parsed_data)} 个项目\n")
        
        # 角色名称映射（便于阅读）
        role_names = {
            Qt.DisplayRole: "DisplayRole (显示文本)",
            Qt.BackgroundRole: "BackgroundRole (背景色)",
            Qt.ForegroundRole: "ForegroundRole (文本色)",
            Qt.ToolTipRole: "ToolTipRole (提示文本)",
            Qt.DecorationRole: "DecorationRole (装饰图标)",
            Qt.EditRole: "EditRole (编辑文本)"
        }
        
        # 逐个显示解析的项目
        for i, item in enumerate(parsed_data, 1):
            self.parser_output.append(f"项目 {i}:")
            self.parser_output.append(f"  原始行索引: {item['row']}")
            self.parser_output.append(f"  原始列索引: {item['col']}")
            self.parser_output.append("  数据角色及值:")
            
            for role, value in item['roles'].items():
                role_name = role_names.get(role, f"未知角色 (代码: {role})")
                self.parser_output.append(f"    {role_name}: {value}")
            
            self.parser_output.append("")  # 空行分隔

    def _insert_data(self, parsed_data, pos):
        """将解析后的数据插入到表格中"""
        # 获取拖放目标位置
        index = self.indexAt(pos)
        target_row = index.row() if index.isValid() else self.rowCount()
        target_col = index.column() if index.isValid() else 0
        
        current_row, current_col = target_row, target_col
        
        for item_data in parsed_data:
            # 处理列溢出，自动换行
            if current_col >= self.columnCount():
                current_row += 1
                current_col = 0
                if current_row >= self.rowCount():
                    self.insertRow(current_row)
            
            # 创建新单元格
            new_item = QTableWidgetItem()
            
            # 应用解析到的所有角色属性
            roles = item_data['roles']
            if Qt.DisplayRole in roles:
                new_item.setText(str(roles[Qt.DisplayRole]))
            if Qt.BackgroundRole in roles:
                new_item.setBackground(roles[Qt.BackgroundRole])
            if Qt.ForegroundRole in roles:
                new_item.setForeground(roles[Qt.ForegroundRole])
            if Qt.ToolTipRole in roles:
                new_item.setToolTip(str(roles[Qt.ToolTipRole]))
                
            new_item.setTextAlignment(Qt.AlignCenter)
            self.setItem(current_row, current_col, new_item)
            
            current_col += 1

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("解析 application/x-qabstractitemmodeldatalist 格式")
        self.setGeometry(100, 100, 500, 400)
        
        # 创建界面布局
        main_layout = QVBoxLayout()
        
        # 添加说明标签
        info_label = QLabel("""
        演示解析 Qt 表格默认拖放格式 application/x-qabstractitemmodeldatalist<br>
        操作: 从左侧表格拖动单元格到右侧区域，将显示解析结果并插入数据
        """)
        main_layout.addWidget(info_label)
        
        # 创建分割器，方便查看表格和解析结果
        splitter = QSplitter(Qt.Vertical)
        
        # 添加表格和解析结果显示
        self.table = DataParserTable()
        splitter.addWidget(self.table)
        splitter.addWidget(self.table.parser_output)
        
        # 设置分割器初始大小
        splitter.setSizes([400, 300])
        
        main_layout.addWidget(splitter)
        self.setLayout(main_layout)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
    